package com.kate.base.singleton;

/**
 * 单例模式实现方式一：饿汉式
 * 【问题1：再多线程场景下可能出现线程不安全，】
 * 测试步骤
 *  1.创建两个线程，线程中同时去获取当前实例
 *  2.在getInstance方法的if判断出打断点，
 *  3.调试模式启动
 * 【问题2：同步方法，导致大量线程阻塞，影响执行效率】
 *  解决办法：同步块
 * 【问题3：由于重排序的存在，可能会导致空指针异常】
 *      1）java中new一个对象其实分3步，而且这3步并不是一个原子操作(要么同时成功，要么同时失败)：
 *          1）开启空间
 *          2）创建实例
 *          3）将对象地址赋值给引用
 *      重排序：第2，3执行顺序是相反的
 *  解决：volatile能修饰的变量，读与写不能重排序的
 *  【问题4：DCL仍然在序列化和反序列化时，造成创建多次实例】
 *  解决方法：Doug Lea 是java并发包下并发类的作者，推荐使用静态内部类
 *  ☆☆☆☆☆单例模式推荐方式一：静态内部类
 *  原理：加载并实例化外部类时，并不会加载和实例化内部类对象，只有当我们调用getInstance()，才会去加载实例化静态内部类，静态属性，
 *  ，且加载在一次。
 *  优点：1.线程安全  2.无需加锁，性能好  3.支持延迟加载
 * ☆☆☆☆☆单例模式推荐方式二：枚举方式
 *  优点：1.线程安全  2.无需加锁，性能好
 *
 */
public class LazySingleton {
    //2.定义静态常量引用
    private static volatile LazySingleton instance = null;
    //1.构造方法私有
    private LazySingleton(){
        System.out.println("构造对象");
    }
    //3.提供公有的返回单列的方法
    public static  LazySingleton getInstance(){
        if(instance==null){//DCL  double check lock
            synchronized (LazySingleton.class){
                if(instance==null){
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}
